﻿///////////////////////////////////////////////////////////////////////////////
// File:        Summary.hpp
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////


#ifndef PINGPONG_SUMMARY_HPP_
#define PINGPONG_SUMMARY_HPP_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#if defined(__WINDOWS__)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif

#include <stdio.h>

class Summary
{
public:
    Summary(void)
        : sec_(0)
        , connLoad_(0)
        , packetsSndTransferred_(0)
        , packetsRcvTransferred_(0)
        , packetsTransferred_(0)
        , bytsTransferred_(0)
    {

    }

    ~Summary(void)
    {

    }

    void inc_ConnLoad(void)
    {
#if defined(__WINDOWS__)
        ::InterlockedIncrement((long *)&connLoad_);
#elif defined(__LINUX__)
        ::__sync_add_and_fetch(&connLoad_, 1);
#endif
    }

    void dec_ConnLoad(void)
    {
#if defined(__WINDOWS__)
        ::InterlockedDecrement((long *)&connLoad_);
#elif defined(__LINUX__)
        ::__sync_sub_and_fetch(&connLoad_, 1);
#endif
    }

    void inc_SndPackets(void)
    {
#if defined(__WINDOWS__)
        ::InterlockedIncrement((long *)&packetsSndTransferred_);
#elif defined(__LINUX__)
        ::__sync_add_and_fetch(&packetsSndTransferred_, 1);
#endif
    }

    void inc_RcvPackets(void)
    {
#if defined(__WINDOWS__)
        ::InterlockedIncrement((long *)&packetsRcvTransferred_);
#elif defined(__LINUX__)
        ::__sync_add_and_fetch(&packetsRcvTransferred_, 1);
#endif
    }

    void inc_Packets(void)
    {
#if defined(__WINDOWS__)
        ::InterlockedIncrement((long *)&packetsTransferred_);
#elif defined(__LINUX__)
        ::__sync_add_and_fetch(&packetsTransferred_, 1);
#endif
    }

    void add_Bytes(unsigned long long x)
    {
#if defined(__WINDOWS__)
        ::InterlockedAdd64((long long *)&bytsTransferred_, x);
#elif defined(__LINUX__)
        ::__sync_add_and_fetch(&bytsTransferred_, x);
#endif
    }

    int getLoad(void) const
    {
        return connLoad_;
    }

    void dump(void)
    {
        static unsigned long secSPackets = 0;
        static unsigned long secRPackets = 0;
        static unsigned long secPackets = 0;
        static unsigned long long secByts = 0;

        ++sec_;
        secSPackets = packetsSndTransferred_ - secSPackets;
        secRPackets = packetsRcvTransferred_ - secRPackets;
        secPackets = packetsTransferred_ - secPackets;
        secByts = bytsTransferred_ - secByts;

        printf("Total Connections：                %d\n", connLoad_);
        printf("Total Packets：                    %ld %ld/%ld\n", packetsTransferred_, 
            packetsSndTransferred_, packetsRcvTransferred_);
        printf("Total Bytes：                      %lld [B] %lld [K] %lld [M]\n",
            bytsTransferred_, bytsTransferred_ / (1024), bytsTransferred_ / (1024 * 1024));

        printf("Packets Per Second：               %ld %ld/%ld\n", secPackets, secSPackets, secRPackets);
        printf("Bytes Per Second：                 %lld [B] %lld [K] %lld [M]\n",
            secByts, secByts / (1024), secByts / (1024 * 1024));

        printf("AV Packets Per Second：            %ld %ld/%ld\n", packetsTransferred_ / sec_,
            packetsSndTransferred_ / sec_, packetsRcvTransferred_ / sec_);
        unsigned long long x = bytsTransferred_ / sec_;
        printf("AV Bytes Per Second：              %lld [B] %lld [K] %lld [M]\n\n",
            x, x / (1024), x / (1024 * 1024));

        secSPackets = packetsSndTransferred_;
        secRPackets = packetsRcvTransferred_;
        secPackets = packetsTransferred_;
        secByts = bytsTransferred_;
    }

private:
    int sec_;
    int connLoad_;
    volatile unsigned long packetsSndTransferred_;
    volatile unsigned long packetsRcvTransferred_;
    volatile unsigned long packetsTransferred_;
    volatile unsigned long long bytsTransferred_;
};

extern Summary gSummary;

#endif //PINGPONG_SUMMARY_HPP_
